import {
  MyColumnCellRenderOptions,
  MyColumnCellRenderParams,
  MyColumnEditRenderOptions,
  MyColumnEditRenderParams
} from "../MyTables";
import {PluginExtend} from "../pluginExtend";
import XEUtils from "xe-utils";
import {CreateElement} from "vue";
import {
  ColumnCellRenderOptions,
  ColumnEditRenderOptions,
  FormItemRenderOptions,
  FormItemRenderParams,
  OptionProps,
  SlotVNodeType
} from "vxe-table";
import {
  createExportMethod,
  getCellEditFilterProps,
  getCellLabelVNs,
  getEditOns,
  getFilterOns,
  getItemOns,
  getItemProps,
  getNativeOns,
  handleConfirmFilter, isEmptyValue,
} from "../pluginUtils";
import {RendererMapOptions} from "vxe-table/types/v-x-e-table/renderer";

function renderOptions(h: CreateElement, options: any[], optionProps: OptionProps) {
  const labelProp = optionProps.label || 'label'
  const valueProp = optionProps.value || 'value'
  return XEUtils.map(options, (item, oIndex) => {
    return h('el-option', {
      key: oIndex,
      props: {
        value: item[valueProp],
        label: item[labelProp],
        disabled: item.disabled
      }
    })
  })
}

function getSelectCellValue(renderOpts: MyColumnEditRenderOptions, params: MyColumnCellRenderParams) {
  const options = PluginExtend.optionsPlus(renderOpts, params)
  const {optionGroups, props = {}, optionProps = {}, optionGroupProps = {}} = renderOpts
  const {row, column} = params
  const $table: any = params.$table
  const labelProp = optionProps.label || 'label'
  const valueProp = optionProps.value || 'value'
  const groupOptions = optionGroupProps.options || 'options'
  const cellValue = XEUtils.get(row, column.property)
  const colid = column.id
  let rest: any
  let cellData: any
  if (props.filterable) {
    const fullAllDataRowMap: Map<any, any> = $table.fullAllDataRowMap
    const cacheCell = fullAllDataRowMap.has(row)
    if (cacheCell) {
      rest = fullAllDataRowMap.get(row)
      cellData = rest.cellData
      if (!cellData) {
        cellData = fullAllDataRowMap.get(row).cellData = {}
      }
    }
    if (rest && cellData[colid] && cellData[colid].value === cellValue) {
      return cellData[colid].label
    }
  }
  if (!isEmptyValue(cellValue)) {
    const selectlabel = XEUtils.map(props.multiple ? cellValue : [cellValue], optionGroups
      ? (value) => {
        let selectItem: any
        for (let index = 0; index < optionGroups.length; index++) {
          selectItem = XEUtils.find(optionGroups[index][groupOptions], (item) => item[valueProp] === value)
          if (selectItem) {
            break
          }
        }
        return selectItem ? selectItem[labelProp] : value
      }
      : (value) => {
        const selectItem = XEUtils.find(options, (item) => item[valueProp] === value)
        return selectItem ? selectItem[labelProp] : value
      }).join(', ')
    if (cellData && options.length) {
      cellData[colid] = {value: cellValue, label: selectlabel}
    }
    return selectlabel
  }
  return ''
}


const value: RendererMapOptions = {
  renderDefault(h: CreateElement, renderOpts: ColumnCellRenderOptions | ColumnEditRenderOptions, params: MyColumnEditRenderParams | MyColumnCellRenderParams): SlotVNodeType | SlotVNodeType[] {
    // @ts-ignore
    return value.renderEdit(h, renderOpts as MyColumnEditRenderOptions, params)
  },
  renderEdit(h, renderOpts: MyColumnEditRenderOptions, params: MyColumnEditRenderParams | MyColumnCellRenderParams) {
    const options = PluginExtend.optionsPlus(renderOpts, params)
    const {
      optionGroups,
      optionProps = {},
      optionGroupProps = {}
    } = renderOpts
    const {row, column} = params
    const {attrs} = renderOpts
    const cellValue = XEUtils.get(row, column.property)
    const props = getCellEditFilterProps(renderOpts, params, cellValue)
    const on = getEditOns(renderOpts, params)
    const nativeOn = getNativeOns(renderOpts, params)
    if (optionGroups) {
      const groupOptions = optionGroupProps.options || 'options'
      const groupLabel = optionGroupProps.label || 'label'
      return [
        h('el-select', {
          attrs,
          props,
          on,
          nativeOn
        }, XEUtils.map(optionGroups, (group, gIndex) => {
          return h('el-option-group', {
            key: gIndex,
            props: {
              label: group[groupLabel]
            }
          }, renderOptions(h, group[groupOptions], optionProps))
        }))
      ]
    }
    return [
      h('el-select', {
        props,
        attrs,
        on,
        nativeOn
      }, renderOptions(h, options, optionProps))
    ]
  },
  renderCell(h, renderOpts: MyColumnCellRenderOptions, params: MyColumnEditRenderParams | MyColumnCellRenderParams) {
    return getCellLabelVNs(h, renderOpts, params, getSelectCellValue(renderOpts as MyColumnEditRenderOptions, params))
  },
  renderFilter(h, renderOpts, params) {
    const {options = [], optionGroups, optionProps = {}, optionGroupProps = {}} = renderOpts
    const groupOptions = optionGroupProps.options || 'options'
    const groupLabel = optionGroupProps.label || 'label'
    const {column} = params
    const {attrs} = renderOpts
    const nativeOn = getNativeOns(renderOpts, params)
    return [
      h('div', {
        class: 'vxe-table--filter-element-wrapper'
      }, optionGroups
        ? column.filters.map((option, oIndex) => {
          const optionValue = option.data
          const props = getCellEditFilterProps(renderOpts, params, optionValue)
          return h('el-select', {
            key: oIndex,
            attrs,
            props,
            on: getFilterOns(renderOpts, params, option, () => {
              // 处理 change 事件相关逻辑
              handleConfirmFilter(params, props.multiple ? (option.data && option.data.length > 0) : !XEUtils.eqNull(option.data), option)
            }),
            nativeOn
          }, XEUtils.map(optionGroups, (group, gIndex) => {
            return h('el-option-group', {
              key: gIndex,
              props: {
                label: group[groupLabel]
              }
            }, renderOptions(h, group[groupOptions], optionProps))
          }))
        })
        : column.filters.map((option, oIndex) => {
          const optionValue = option.data
          const props = getCellEditFilterProps(renderOpts, params, optionValue)
          return h('el-select', {
            key: oIndex,
            attrs,
            props,
            on: getFilterOns(renderOpts, params, option, () => {
              // 处理 change 事件相关逻辑
              handleConfirmFilter(params, props.multiple ? (option.data && option.data.length > 0) : !XEUtils.eqNull(option.data), option)
            }),
            nativeOn
          }, renderOptions(h, options, optionProps))
        }))
    ]
  },
  defaultFilterMethod(params) {
    const {option, row, column} = params
    const {data} = option
    const {property, filterRender: renderOpts} = column
    const {props = {}} = renderOpts
    const cellValue = XEUtils.get(row, property)
    if (props.multiple) {
      if (XEUtils.isArray(cellValue)) {
        return XEUtils.includeArrays(cellValue, data)
      }
      return data.indexOf(cellValue) > -1
    }
    /* eslint-disable eqeqeq */
    return cellValue == data
  },
  renderItem(h: CreateElement, renderOpts: FormItemRenderOptions, params: FormItemRenderParams) {
    const {options = [], optionGroups, optionProps = {}, optionGroupProps = {}} = renderOpts
    const {data, property} = params
    const {attrs} = renderOpts
    const itemValue = XEUtils.get(data, property)
    const props = getItemProps(renderOpts, params, itemValue)
    const on = getItemOns(renderOpts, params)
    const nativeOn = getNativeOns(renderOpts, params)
    if (optionGroups) {
      const groupOptions = optionGroupProps.options || 'options'
      const groupLabel = optionGroupProps.label || 'label'
      return [
        h('el-select', {
          attrs,
          props,
          on,
          nativeOn
        }, XEUtils.map(optionGroups, (group, gIndex) => {
          return h('el-option-group', {
            props: {
              label: group[groupLabel]
            },
            key: gIndex
          }, renderOptions(h, group[groupOptions], optionProps))
        }))
      ]
    }
    return [
      h('el-select', {
        attrs,
        props,
        on,
        nativeOn
      }, renderOptions(h, options, optionProps))
    ]
  },
  renderItemContent(h, renderOpts, params) {
    const {options = [], optionGroups, optionProps = {}, optionGroupProps = {}} = renderOpts
    const {data, property} = params
    const {attrs} = renderOpts
    const itemValue = XEUtils.get(data, property)
    const props = getItemProps(renderOpts, params, itemValue)
    const on = getItemOns(renderOpts, params)
    const nativeOn = getNativeOns(renderOpts, params)
    if (optionGroups) {
      const groupOptions = optionGroupProps.options || 'options'
      const groupLabel = optionGroupProps.label || 'label'
      return [
        h('el-select', {
          attrs,
          props,
          on,
          nativeOn
        }, XEUtils.map(optionGroups, (group, gIndex) => {
          return h('el-option-group', {
            props: {
              label: group[groupLabel]
            },
            key: gIndex
          }, renderOptions(h, group[groupOptions], optionProps))
        }))
      ]
    }
    return [
      h('el-select', {
        attrs,
        props,
        on,
        nativeOn
      }, renderOptions(h, options, optionProps))
    ]
  },
  cellExportMethod: createExportMethod(getSelectCellValue),
  exportMethod: createExportMethod(getSelectCellValue)
}

export default value
